﻿//-----------------------------------------------------------------------
// <copyright file="Program.cs" company="DylanBox">
// Copyright (c) DylanBox Corporation. All rights reserved.
// </copyright>
// <summary></summary>
// <reference>
//      <<2>>
//    Actually, Events are based on the Observer or Publish/Subscribe design pattern.
//      :-)
//  Ref: http://www.dotnetscraps.com/dotnetscraps/post/Explaining-Delegates-in-C-Part-2-(Events).aspx
// </reference>
// <author>Dylan</author>
//-----------------------------------------------------------------------
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DelegateAndEvent
{
    //There are 3 rules which are MANDATORY when you are planning to create events
    //Rule 1> The delegate must be defined with two arguments
    //Rule 2> These arguments always represent TWO objects… 
    //          The Publisher (object that raised the event)
    //          Event Information object
    //Rule 3> The 2nd object HAS to be derived from EventArgs

    //To comply with Rule 3 we create a LoggerEventArgs which is derived from EventArgs
    class LoggerEventArgs : EventArgs
    {
        public string UserName
        {
            get;
            private set;
        }  

        //constructor to initialize the UserName property
        public LoggerEventArgs(string userName)
        {
            this.UserName = userName;
        }     
    };

    //To comply with Rule 1 and 2, in the publisher class we created a delegate and event declaration
    class InventoryManager // Publisher
    {
        public delegate void LoggerEventHandler(object source, LoggerEventArgs e);
        public event LoggerEventHandler OnInventoryUpdate;

        //This method will fire an event called OnInventoryUpdate whenever called
        public void LogEvent(string username)
        {
            LoggerEventArgs e = new LoggerEventArgs(username);
            if (OnInventoryUpdate != null)
            {
                Console.WriteLine("LogEvent > Raising events to all subscribers...\n");
                OnInventoryUpdate(this, e);
            }
        }
    };

    class InventoryLogger // Subscriber
    {
        InventoryManager inventoryManager;
        public InventoryLogger(InventoryManager inventoryManager)
        {
            Console.WriteLine("InventoryWatcher > Subscribing to OnInventoryUpdate event...\n");
            this.inventoryManager = inventoryManager;

            //Wiring the event so that the event is fired
            inventoryManager.OnInventoryUpdate += new InventoryManager.LoggerEventHandler(OnInventoryUpdate);
        }

        void OnInventoryUpdate(object source, LoggerEventArgs e)
        {
            Console.WriteLine("The guy who changed this inventory was... " + e.UserName);
        }
    }

    class DelegateEvents
    {
        public static void Main()
        {
            InventoryManager inventoryManager = new InventoryManager();

            Console.WriteLine("Main > Instantiating the subscriber... \n\n");
            InventoryLogger inventoryLog = new InventoryLogger(inventoryManager);

            inventoryManager.LogEvent("Rahul Soni");
            inventoryManager.LogEvent("Dylan Wang");
            Console.ReadLine();
        }
    };

}
